﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QD.Tools
{
    public static class TypeHelper
    {
        public static object ChanageType(this object value, Type convertsionType)
        {
            //判断convertsionType类型是否为泛型，因为nullable是泛型类,
            if (convertsionType.IsGenericType &&
                //判断convertsionType是否为nullable泛型类
                convertsionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null || value.ToString().Length == 0)
                {
                    return null;
                }

                //如果convertsionType为nullable类，声明一个NullableConverter类，该类提供从Nullable类到基础基元类型的转换
                NullableConverter nullableConverter = new NullableConverter(convertsionType);
                //将convertsionType转换为nullable对的基础基元类型
                convertsionType = nullableConverter.UnderlyingType;
            }

            if (value == null || value.ToString().Length == 0)
            {
                if (convertsionType == typeof(DateTime))
                    return DateTime.Now;
                else if (convertsionType == typeof(Guid))
                    return Guid.NewGuid();
                else if (convertsionType == typeof(bool))
                    return false;
                else if (convertsionType != typeof(string))
                    return Convert.ChangeType(0, convertsionType);
                else
                    return "";
            }
            else
            {
                if (convertsionType.BaseType == typeof(Enum))
                    return Enum.Parse(convertsionType, value.ToString());
                else if (convertsionType == typeof(Guid))
                    return new Guid(value.ToString());
                else
                    return Convert.ChangeType(value.ToString().Trim(), convertsionType);
            }
        }
        // <summary>
        /// 根据字符串取实际数据类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Type GetTypeByString(string type)
        {
            switch (type.ToLower())
            {
                case "bool":
                    return Type.GetType("System.Boolean", true, true);
                case "byte":
                    return Type.GetType("System.Byte", true, true);
                case "sbyte":
                    return Type.GetType("System.SByte", true, true);
                case "char":
                    return Type.GetType("System.Char", true, true);
                case "decimal":
                    return Type.GetType("System.Decimal", true, true);
                case "double":
                    return Type.GetType("System.Double", true, true);
                case "float":
                    return Type.GetType("System.Single", true, true);
                case "int":
                    return Type.GetType("System.Int32", true, true);
                case "uint":
                    return Type.GetType("System.UInt32", true, true);
                case "long":
                    return Type.GetType("System.Int64", true, true);
                case "ulong":
                    return Type.GetType("System.UInt64", true, true);
                case "object":
                    return Type.GetType("System.Object", true, true);
                case "short":
                    return Type.GetType("System.Int16", true, true);
                case "ushort":
                    return Type.GetType("System.UInt16", true, true);
                case "string":
                    return Type.GetType("System.String", true, true);
                case "date":
                case "datetime":
                    return Type.GetType("System.DateTime", true, true);
                case "guid":
                    return Type.GetType("System.Guid", true, true);
                default:
                    return Type.GetType(type, true, true);
            }
        }
        /// <summary>
        /// 数据类型转换
        /// </summary>
        /// <param name="value"></param>
        /// <param name="convertsionType"></param>
        /// <returns></returns>
        public static object ChangeType(this object value, Type convertsionType)
        {
            //判断convertsionType类型是否为泛型，因为nullable是泛型类,
            if (convertsionType.IsGenericType &&
                //判断convertsionType是否为nullable泛型类
                convertsionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null || value.ToString().Length == 0)
                {
                    return null;
                }

                //如果convertsionType为nullable类，声明一个NullableConverter类，该类提供从Nullable类到基础基元类型的转换
                NullableConverter nullableConverter = new NullableConverter(convertsionType);
                //将convertsionType转换为nullable对的基础基元类型
                convertsionType = nullableConverter.UnderlyingType;
            }
            object returnType = null;

            if (value == null || value.ToString() == "")
            {
                //字符
                if (convertsionType.FullName == "System.String")
                {
                    returnType = value;
                }
                //数字
                else if (convertsionType.FullName == "System.Int16")
                {
                    returnType = default(System.Int16);
                }
                else if (convertsionType.FullName == "System.Int32")
                {
                    returnType = default(System.Int32);
                }
                else if (convertsionType.FullName == "System.Int64")
                {
                    returnType = default(System.Int64);
                }
                else if (convertsionType.FullName == "System.UInt16")
                {
                    returnType = default(System.UInt16);
                }
                else if (convertsionType.FullName == "System.UInt32")
                {
                    returnType = default(System.UInt32);
                }
                else if (convertsionType.FullName == "System.UInt64")
                {
                    returnType = default(System.UInt64);
                }
                else if (convertsionType.FullName == "System.Double")
                {
                    returnType = default(System.Double);
                }
                else if (convertsionType.FullName == "System.Decimal")
                {
                    returnType = default(System.Decimal);
                }
                else if (convertsionType.FullName == "System.Byte")
                {
                    returnType = default(System.Byte);
                }
                else if (convertsionType.FullName == "System.SByte")
                {
                    returnType = default(System.SByte);
                }
                else if (convertsionType.FullName == "System.Single")
                {
                    returnType = default(System.Single);
                }
                //DateTime
                else if (convertsionType.FullName == "System.DateTime")
                {
                    returnType = default(System.DateTime);
                }
                //Guid
                else if (convertsionType.FullName == "System.Guid")
                {
                    returnType = default(System.Guid);
                }
                //Boolean
                else if (convertsionType.FullName == "System.Boolean")
                {
                    returnType = default(System.Boolean);
                }
                //Char
                else if (convertsionType.FullName == "System.Char")
                {
                    returnType = value;
                }
                else
                {
                    try
                    {
                        returnType = Convert.ChangeType(value, convertsionType);
                    }
                    catch (Exception except)
                    {
                        //Common.LogHelper.AddLogTxt(except.Source + Environment.NewLine + except.Message + Environment.NewLine + except.StackTrace + "value == null,convertsionType=" + convertsionType.FullName);

                    }
                }
            }
            else if (value.GetType().FullName == "System.Boolean" && convertsionType.FullName == "System.Int32")
            {
                if (value.ToString().ToLower() == "false")
                {
                    returnType = 0;
                }
                else
                {
                    returnType = 1;
                }
            }
            else if ((value.GetType().FullName == "System.Int32" || value.GetType().FullName == "System.String") && convertsionType.FullName == "System.Boolean")
            {
                if (value.ToString() == "0" || value.ToString().ToLower() == "false" || value.ToString().ToLower() == "")
                {
                    returnType = false;
                }
                else
                {
                    returnType = true;
                }
            }
            else if (value.GetType().FullName == "System.String" && convertsionType.FullName == "System.Guid")
            {
                Guid tempValue;
                if (Guid.TryParse(value.ToString(), out tempValue))
                {
                    returnType = tempValue;
                }
                else
                {
                    returnType = default(Guid);
                }
            }
            else if (convertsionType.FullName == "System.DateTime")
            {
                DateTime tempValue;
                if (DateTime.TryParse(value.ToString(), out tempValue))
                {
                    returnType = tempValue;
                }
                else
                {
                    returnType = default(DateTime);
                }
            }
            else
            {
                try
                {

                    returnType = Convert.ChangeType(value, convertsionType);
                }
                catch (Exception except)
                {
                    //Common.LogHelper.AddLogTxt(except.Source + Environment.NewLine + except.Message + Environment.NewLine + except.StackTrace + "value == " + value.ToString() + ",convertsionType=" + convertsionType.FullName);

                }
            }
            return returnType;
        }
    }
}
